package org.moriwuzhe.shuttle.spring.register;

import org.moriwuzhe.shuttle.common.utils.StringUtils;
import org.moriwuzhe.shuttle.spring.annotation.ShuttleComponentScan;
import org.moriwuzhe.shuttle.spring.utils.ClassUtil;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;

import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;

public class ShuttleComponentScanRegister implements ImportBeanDefinitionRegistrar{

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        Class<ShuttleServiceBeanPostProcessor> shuttleServiceBeanPostProcessorClass = ShuttleServiceBeanPostProcessor.class;
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(shuttleServiceBeanPostProcessorClass);
        String simpleName = shuttleServiceBeanPostProcessorClass.getSimpleName();
        String shuttleServiceBeanPostProcessorBeanName = simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1);
        registry.registerBeanDefinition(shuttleServiceBeanPostProcessorBeanName, builder.getBeanDefinition());


        Set<Class<?>> packagesToScan = getPackagesToScan(importingClassMetadata);
        registerServiceClassPostProcessor(packagesToScan, registry);
    }

    private void registerServiceClassPostProcessor(Set<Class<?>> packagesClass, BeanDefinitionRegistry registry) {
        for (Class<?> aClass : packagesClass) {
            GenericBeanDefinition beanDefinition = new GenericBeanDefinition();

            if (aClass.isInterface()) {
                continue;
            }
            beanDefinition.setBeanClass(aClass);

            registry.registerBeanDefinition(aClass.getName(), beanDefinition);
        }
    }

    private Set<Class<?>> getPackagesToScan(AnnotationMetadata metadata) {
        AnnotationAttributes attributes = AnnotationAttributes
                .fromMap(metadata.getAnnotationAttributes(ShuttleComponentScan.class.getName()));
        Set<Class<?>> packagesClass = new LinkedHashSet<>();
        if (Objects.isNull(attributes)) {
            return packagesClass;
        }

        String[] basePackages = attributes.getStringArray("basePackages");
        if (basePackages.length == 0) {
            String className = metadata.getClassName();
            packagesClass.addAll(ClassUtil.scanPackage(className.substring(0, className.lastIndexOf("."))));
        }
        for (String basePackage : basePackages) {
            packagesClass.addAll(ClassUtil.scanPackage(basePackage));
        }
        return packagesClass;
    }

}
